package com.jcj.jcjrpc.core.config;

import com.jcj.jcjrpc.core.api.*;
import com.jcj.jcjrpc.core.cluster.GrayRouter;
import com.jcj.jcjrpc.core.cluster.RoundRibonLoadBalancer;
import com.jcj.jcjrpc.core.consumer.ConsumerBootstrap;
import com.jcj.jcjrpc.core.filter.ContextParameterFilter;
import com.jcj.jcjrpc.core.meta.InstanceMeta;
import com.jcj.jcjrpc.core.registry.jcj.JcjRegistryCenter;
import com.jcj.jcjrpc.core.registry.zk.ZkRegistryCenter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;

import java.util.List;

@Slf4j
@Configuration
@Import({AppProperties.class, ConsumerProperties.class})
public class ConsumerConfig {

    @Autowired
    AppProperties appProperties;

    @Autowired
    ConsumerProperties consumerProperties;

    @Bean
    ConsumerBootstrap consumerBootstrap() {
        log.debug("102 createConsumerBootstrap");
        return new ConsumerBootstrap();
    }

    @Bean
    @Order(Integer.MIN_VALUE + 1)
    public ApplicationRunner consumerBootstrapRunner(@Autowired ConsumerBootstrap consumerBootstrap) {
        return x -> {
            log.debug("consumerBootstrap starting ...");
//            System.out.println("jcjrpc.providers => " + String.join(",", servers));

            consumerBootstrap.start();
            log.debug("consumerBootstrap started ...");
        };
    }

    @Bean
    public LoadBalancer<InstanceMeta> loadBalancer() {
        return new RoundRibonLoadBalancer();
    }

    @Bean
    public Router<InstanceMeta> router() {
        return new GrayRouter(consumerProperties.getGrayRatio());
    }

    @Bean(initMethod = "start", destroyMethod = "stop")
    @ConditionalOnMissingBean
    public RegistryCenter consumer_rc() {
        return new JcjRegistryCenter();
    }

    @Bean
    public Filter defaultFilter() {
        return new ContextParameterFilter();
    }


    @Bean
    @RefreshScope
    public RpcContext createContext(@Autowired Router router,
                                    @Autowired LoadBalancer loadBalancer,
                                    @Autowired List<Filter> filters) {
        RpcContext context = new RpcContext();
        context.setRouter(router);
        context.setLoadBalancer(loadBalancer);
        context.setFilters(filters);
        context.getParameters().put("app.id", appProperties.getId());
        context.getParameters().put("app.namespace", appProperties.getNamespace());
        context.getParameters().put("app.env", appProperties.getEnv());
        context.getParameters().put("consumer.retries", String.valueOf(consumerProperties.getRetries()));
        context.getParameters().put("consumer.timeout", String.valueOf(consumerProperties.getTimeout()));
        context.getParameters().put("consumer.faultLimit", String.valueOf(consumerProperties.getFaultLimit()));
        context.getParameters().put("consumer.halfOpenInitialDelay", String.valueOf(consumerProperties.getHalfOpenInitialDelay()));
        context.getParameters().put("consumer.halfOpenDelay", String.valueOf(consumerProperties.getHalfOpenDelay()));
        return context;
    }

//    @Bean
//    public Filter filter1() {
//        return new CacheFilter();
//    }

    //    @Bean
//    public Filter filter2() {
//        return new MockFilter();
//    }


//    @Bean
//    @ConditionalOnMissingBean
//    @ConditionalOnProperty(prefix = "apollo.bootstrap", value = "enabled")
//    ApolloChangedListener consumer_apolloChangedListener() {
//        return new ApolloChangedListener();
//    }
}
